#ifndef COMMONS_H_INCLUDED
#define COMMONS_H_INCLUDED

#include <stdint.h>

////////////////////////////////////////////////////////////////////////////////////////////////////

uint8_t SingletonReadMemory( uint16_t );
void    SingletonWriteMemory( uint16_t, uint8_t );

////////////////////////////////////////////////////////////////////////////////////////////////////

#define ROM_SIZE        0x10000
#define RAM_BANK_SIZE   0x2000

////////////////////////////////////////////////////////////////////////////////////////////////////

#define FLAG_Z  0x80
#define FLAG_N  0x40
#define FLAG_H  0x20
#define FLAG_C  0x10

////////////////////////////////////////////////////////////////////////////////////////////////////

#define PPU_MODE_2_CYCLES   ( 80 )
#define PPU_MODE_3_CYCLES   ( 172 + PPU_MODE_2_CYCLES )
#define PPU_MODE_0_CYCLES   ( 204 + PPU_MODE_3_CYCLES )
#define PPU_SCANLINE_CYCLES 456 // 80 + 172 + 204
#define PPU_MAX_SCANLINE    153

////////////////////////////////////////////////////////////////////////////////////////////////////

#define INTERRUPT_VBLANK    0x01
#define INTERRUPT_LCD       0x02

////////////////////////////////////////////////////////////////////////////////////////////////////

typedef union ___PAIR_REGISTER {
    uint16_t    w;
    struct {
        uint8_t l;
        uint8_t h;
    };
} PAIR_REGISTER;

////////////////////////////////////////////////////////////////////////////////////////////////////

static const int OPCODE_CYCLES[ 0x100 ] = {
//      0   1   2  3   4   5   6  7  8   9  A   B  C  D   E  F
/* 0 */ 0 , 12, 8, 8 , 4 , 4 , 8, 0, 20, 8, 8 , 8, 4, 4 , 8, 4,
/* 1 */ 0 , 12, 8, 8 , 4 , 4 , 8, 0, 8 , 8, 8 , 8, 4, 4 , 8, 0,
/* 2 */ 8 , 12, 8, 8 , 4 , 4 , 8, 0, 8 , 8, 8 , 8, 4, 4 , 8, 4,
/* 3 */ 8 , 12, 0, 8 , 12, 12, 0, 0, 8 , 8, 0 , 8, 4, 4 , 8, 0,
/* 4 */ 0 , 0 , 0, 0 , 0 , 0 , 0, 4, 0 , 0, 0 , 0, 0, 0 , 0, 4,
/* 5 */ 0 , 0 , 0, 0 , 0 , 0 , 0, 4, 0 , 0, 0 , 0, 0, 0 , 0, 4,
/* 6 */ 0 , 0 , 0, 0 , 0 , 0 , 0, 4, 4 , 0, 0 , 0, 0, 0 , 0, 4,
/* 7 */ 0 , 0 , 0, 0 , 0 , 0 , 0, 8, 4 , 4, 4 , 4, 4, 4 , 8, 4,
/* 8 */ 4 , 4 , 4, 4 , 4 , 4 , 8, 4, 0 , 0, 0 , 0, 0, 0 , 0, 0,
/* 9 */ 0 , 0 , 0, 0 , 0 , 0 , 0, 0, 0 , 0, 0 , 0, 0, 0 , 0, 0,
/* A */ 4 , 4 , 4, 4 , 4 , 4 , 8, 4, 4 , 4, 4 , 4, 4, 4 , 8, 4,
/* B */ 4 , 4 , 4, 4 , 4 , 4 , 8, 4, 4 , 4, 4 , 4, 4, 4 , 8, 4,
/* C */ 8 , 12, 0, 12, 0 , 16, 8, 0, 8 , 8, 0 , 0, 0, 12, 0, 0,
/* D */ 8 , 12, 0, 0 , 0 , 16, 0, 0, 8 , 0, 0 , 0, 0, 0 , 0, 0,
/* E */ 12, 12, 0, 0 , 0 , 16, 8, 0, 0 , 0, 16, 0, 0, 0 , 0, 0,
/* F */ 12, 12, 0, 4 , 0 , 16, 8, 0, 12, 0, 16, 4, 0, 0 , 8, 0,
};

////////////////////////////////////////////////////////////////////////////////////////////////////

static const int CB_OPCODE_CYCLES[ 0x100 ] = {
//      0  1  2  3  4  5  6   7  8  9  A  B  C  D  E   F
/* 0 */ 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0,
/* 1 */ 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0,
/* 2 */ 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0,
/* 3 */ 8, 8, 8, 8, 8, 8, 16, 8, 0, 0, 0, 0, 0, 0, 0 , 0,
/* 4 */ 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
/* 5 */ 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
/* 6 */ 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
/* 7 */ 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
/* 8 */ 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
/* 9 */ 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
/* A */ 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
/* B */ 8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
/* C */ 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0,
/* D */ 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0,
/* E */ 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0,
/* F */ 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0,
};

////////////////////////////////////////////////////////////////////////////////////////////////////

#endif